PrepareLevel1:	
	;; VRAM C784
	move.l	#$47840003,d7
	bsr	PrepareLevelCommon

	;; copy ground tiles over VRAM 2000
        move.l   #$60000000,(a4)
        lea      StartROAD2Tiles(pc),a5
        move.w   #((EndROAD2Tiles-StartROAD2Tiles)/2-1),d5
Road2TileCopy:
        move.w   (a5)+,(a3)
        dbf      d5,Road2TileCopy

	;; copy road2 tiles
	move.w	#31,d0
	;; VRAM CB80
	move.l	#$4B800003,d1
Level1Road2MapLoop:	
	lea     StartROAD2Map(pc),a5
	move.w  #$0100,d4
        moveq   #(ROAD2TileWidth-1),d5
        moveq   #(ROAD2TileHeight-1),d6
	move.l	d1,d7
	addi.l	#$00040000,d1
	bsr	CopyMap
	dbf     d0,Level1Road2MapLoop

	btst	#TwoPlayerFlag,Flags
	bne.s	PrepareLevel1TwoPlayer

PrepareLevel1OnePlayer:	
	;; ( truckleft sprite - riley sprite height ) << 8
	move.l	#$00011D00,Level1RileyPositionY
	lea	StartSpriteLevel1Initial(pc),a5
	;; sprite load follows branch
	bra.s	PrepareLevel1Final
	
PrepareLevel1TwoPlayer:
	;; copy road2 tiles
	move.w	#31,d0
	;; VRAM C480
	move.l	#$44800003,d1
Level1TwoPlayerRoad2MapLoop:	
	lea     StartROAD2Map(pc),a5
	move.w  #$0100,d4
        moveq   #(ROAD2TileWidth-1),d5
        moveq   #(ROAD2TileHeight-1),d6
	move.l	d1,d7
	addi.l	#$00040000,d1
	bsr	CopyMap
	dbf     d0,Level1TwoPlayerRoad2MapLoop

	move.l	#$0000AD00,Level1RileyPositionY
	move.l	#$00011D00,Level1Riley2PositionY

	lea	StartSpriteLevel1TwoPlayerInitial(pc),a5

PrepareLevel1Final:	
	bsr	SpriteLoad

	lea	Level1Animate(pc),a5
	move.l	a5,VintAnimate

	bsr	RefreshLetters
	bsr	FadeIn

Level1Loop:
	bsr	WaitForVint

	;; demo mode check
	btst	#DemoFlag,Flags
	beq.s	Level1SkipDemoMode
	;; in demo mode, exit on button press
	btst	#StartButtonFlag,Flags
	bne	PrepareTitleFadeOut
	;; demo only shows for a certain amount of frames
	cmpi.w	#VintWaitDemo,VintWait
	bge	PrepareTitleFadeOut
	;; d1 is our target fake port1hold
	clr.b	d1
	;; determine when to jump or not jump
	move.w	RileySprite+6,d0
	;; add 16/2 middle of riley
	;; subtract 8/2 middle of letter
	;; add 2*20 (amount letter will move till around top of riley's jump)
	addi.w	#(16/2-8/2+2*20),d0
	cmp.w	LetterSprite+6,d0
	blt.s	Level1DemoDoNotJump
	bset	#bitC,d1
Level1DemoDoNotJump:
	;; since game boards are symetrical, apply same input to both ports
	move.b	d1,Port1Hold
	move.b	d1,Port1Press
	move.b	d1,Port2Hold
	move.b	d1,Port2Press
Level1SkipDemoMode:	

	;; check for sprite collision
	move.w   (a4),d0
	andi.b   #$0020,d0
	beq      Level1MoveRiley1

	;; there is a sprite collision
	;; see if letter already $00 (end of word)
	tst.b    LetterSprite+5
	beq.s    Level1Player2Collision
	;; collision check
	lea	RileySprite,a5
	lea	LetterSprite,a6
	bsr	CheckSpriteCollision
	bne.s	Level1Player2Collision

	;; now update the score
	lea     EndScoreAscii,a5
        move.l  #$40900003,d0
	move.w  #(EndScoreAscii-StartScoreAscii-1),d1
	clr.w	d2
	move.b  WordIndex,d2
	;; make high priority (so score will go above other things)
	move.w  #$8000,d4
	bsr	UpdateAndDisplayScoreAndWord

	;; get next character
	clr.w	d0
	move.b  WordIndex,d0
	clr.w	d1
	move.b  WordIndex2,d1
	bsr	GetNextLetter
	move.b	d0,WordIndex

	clr.b	LetterSprite+5
	move.w	#$01C0,LetterSprite+6
	
Level1Player2Collision:	
	btst	#TwoPlayerFlag,Flags
	beq.s	Level1CheckRefreshLetters
	;; see if letter already $00 (end of word)
	tst.b   Letter2Sprite+5
	beq.s   Level1CheckRefreshLetters
	;; collision check
	lea	Riley2Sprite,a5
	lea	Letter2Sprite,a6
	bsr	CheckSpriteCollision
	bne.s	Level1CheckRefreshLetters

	;; now update the score ($30-$39 are valid ASCII numbers)
	lea     EndScoreAscii2,a5
        move.l  #$47900003,d0
	move.w  #(EndScoreAscii2-StartScoreAscii2-1),d1
	clr.w	d2
	move.b  WordIndex2,d2
	;; make high priority (so score will go above other things)
	move.w  #$A000,d4
	bsr	UpdateAndDisplayScoreAndWord

	;; get next character
	clr.w	d0
	move.b  WordIndex2,d0
	clr.w	d1
	move.b  WordIndex,d1
	bsr	GetNextLetter
	move.b	d0,WordIndex2

	clr.b	Letter2Sprite+5
	move.w	#$01C0,Letter2Sprite+6
	
Level1CheckRefreshLetters:	
	bclr	#RefreshLettersWordFlag,WordFlags
	beq.s	Level1CheckNewWord
	bsr	RefreshLetters
	
Level1CheckNewWord:	
	bclr	#NewWordFlag,WordFlags
	beq.s	Level1CheckNewLevel
	;; set x positions of letters to same starting point
	move.w	#$01C0,LetterSprite+6
	move.w	#$01C0,Letter2Sprite+6

Level1CheckNewLevel:	
	;; check if need to go to next level
	;; demo cannot go to another level
	bclr	#NewLevelFlag,WordFlags
	beq.s	Level1MoveRiley1
	btst	#DemoFlag,Flags
	bne.s	Level1MoveRiley1
	bsr	LevelTransition
	bra	PrepareLevel2
	
Level1MoveRiley1:	
	lea	RileySprite,a5
	lea     Level1RileyPositionY,a6
	;; Port1Hold and Port1Press as a word
	move.w	Port1Hold,d3
	bsr	Level1CheckRileyJump
Level1MoveRiley2:	
	lea	Riley2Sprite,a5
	lea     Level1Riley2PositionY,a6
	;; Port2Hold and Port2Press as a word
	move.w	Port2Hold,d3
	bsr	Level1CheckRileyJump

EndLevel1Loop:	
	bra	Level1Loop


Level1Animate:
	movem.l	d0-d3/a5-a6,-(a7)

	;; animate tires of truck
	move.w	 #$07,d0
	bsr    TruckTireSpin

	;; animate road by moving the line that the dashed line is on
	move.w	VintCounter,d0
	;; invert all the bits
	;; (this makes it appear as traveling forwards on road)
	eori.w	#$FFFF,d0
	lsl.w	#1,d0
	;; mask to size of horizontal scrolling size
	andi.w	#$3ff,d0
	;; VRAM DC00+0300
	move.l	#$5F000003,(a4)
	move.w	d0,(a3)
	;; VRAM DC00+0140
	move.l	#$5D400003,(a4)
	move.w	d0,(a3)

	;; move letter to the left
	move.w	 LetterSprite+6,d0
	subq.w	 #2,d0
	cmpi.w	 #$70,d0
	bgt.s	 Level1SkipResetLetterX
	;; wrap around the letter to the right side of the screen
	move.w	 #$01C0,d0
Level1SkipResetLetterX:	
	move.w	 d0,LetterSprite+6

	;; move letter 2 to the left
	move.w	 Letter2Sprite+6,d0
	subq.w	 #2,d0
	cmpi.w	 #$70,d0
	bgt.s	 Level1SkipResetLetter2X
	;; wrap around the letter to the right side of the screen
	move.w	 #$01C0,d0
Level1SkipResetLetter2X:	
	move.w	 d0,Letter2Sprite+6

	lea	RileySprite,a5
	lea     Level1RileyPositionY,a6
	;; Port1Hold and Port1Press as a word
	move.w	Port1Hold,d3
	bsr.s	Level1MoveRiley

	lea	Riley2Sprite,a5
	lea     Level1Riley2PositionY,a6
	;; Port2Hold and Port2Press as a word
	move.w	Port2Hold,d3
	bsr.s	Level1MoveRiley

	movem.l	(a7)+,d0-d3/a5-a6
	rts


	;; used by Level1CheckRileyJump and Level1MoveRiley
	;; to get riley position (d0), riley speed (d1), and
	;; ground position which is the top of the truck (d2)
Level1RileyPositionAndSpeed:	
	;; get RileyPositionY or Riley2PositionY
	move.l	(a6),d0
	;; get RileySpeedY or Riley2SpeedY
	move.w	4(a6),d1

	;; determine top of riley when riley is on top of truck
	clr.l	d2
	;; get top of truck
	move.w	8(a5),d2
	;; subtract height of riley
	;; overlap by one since it looks better
	subi.w	#23,d2
	;; add in 1/256 fraction for smoother movement
	lsl.l	#8,d2

	rts

	;; used sonic physics guide on sonic retro as an example

	;; want to be able to jump 2 * height and somewhere around one second
	;; tried earth's gravity originally
	;; it was way too slow (when comparing to sonic and such)

	;; so wanted 2/3 second jump that was 2 times riley height
	;; since go up and down, time is 20 frames (NTSC)
	;; v = 2 * s / t
	;; v = 2 * 48 pixels / 20 frames
	;; a = v / t
	;; a = 51/256 pixels/frame/frame
	;; v = 1020/256 pixels/frame

	;; Level1CheckRileyJump only checks for a new jump
	;; Level1MoveRiley only handles a jump already in progress
	;; both use the same start and ending code
	
Level1CheckRileyJump:

	;; constants defined in CONSTANT.INC

	bsr.s	Level1RileyPositionAndSpeed
	
	;; if above truck, we are already jumping
	cmp.l	d2,d0
	blt.s	Level1DoneRileyJump
	
	;; look for a new jump from a button press
	andi.b	#(btnA|btnB|btnC),d3
	beq.s	Level1DoneRileyJump

	;; detected a new jump, set our initial speed
	move.w	#JumpVelocity,d1

	;; first frame is a slower jump
	;; kinda like a jump off and helps the button tap have a smaller jump
	;; height
	subi.l	#JumpVelocityReduced,d0
	bra.s	Level1DoneRileyJump

Level1MoveRiley:
	bsr.s	Level1RileyPositionAndSpeed

	;; if above truck, we are already jumping
	cmp.l	d2,d0
	bge.s	Level1DoneRileyJump
	
	;; slow down the speed linearly (constant acceleration)
	subi.w	#JumpGravity,d1

	;; see if care if jump button(s) still pressed
	;; this allows variable height jumps
	cmpi.w	#JumpVelocityReduced,d1
	ble.s	Level1StillJumping

	;; check if jump button(s) still pressed
	andi.w	#((btnA<<8)|(btnB<<8)|(btnC<<8)),d3
	bne.s	Level1StillJumping

	;; restrict the jumping speed to reduce jump height based on when
	;; jump button was released
	move.w	#JumpVelocityReduced,d1
	
Level1StillJumping:	
	;; store the new riley speed
	ext.l	d1
	sub.l	d1,d0

Level1DoneRileyJump:	
	;; make sure riley is still above the top of the truck
	cmp.l	d2,d0
	blt.s	Level1DoneRileyJumpBoundsGood

	;; no more jump, set speed to zero and position to top of truck
	;; and make the jump bounds good again
	move.l	d2,d0
	moveq	#0,d1

Level1DoneRileyJumpBoundsGood:
	;; set RileyPositionY or Riley2PositionY
	move.l	d0,(a6)
	;; set RileySpeedY or Riley2SpeedY
	move.w	d1,4(a6)

	;; update riley y position
	lsr.l	#8,d0
	move.w	d0,(a5)

	rts


	
;;; data used for level 2


StartSpriteLevel1Initial:
RileySpriteLevel1Initial:
	dc.b $01,$1D,$06,$01,$C0,$98,$00,$E2
TruckLeftSpriteLevel1Initial:
	dc.b $01,$34,$0F,$02,$00,$AD,$00,$D7
TruckRightSpriteLevel1Initial:
	dc.b $01,$34,$0B,$04,$00,$BD,$00,$F7
	dc.b $00,$00,$00,$00,$00,$00,$00,$00
LetterSpriteLevel1Initial:
	dc.b $01,$04,$00,$00,$00,$41,$01,$C0
EndSpriteLevel1Initial:	

StartSpriteLevel1TwoPlayerInitial:
RileySpriteLevel1TwoPlayerInitial:
	dc.b $00,$AD,$06,$01,$C0,$98,$00,$E2
TruckLeftSpriteLevel1TwoPlayerInitial:
	dc.b $00,$C4,$0F,$02,$00,$AD,$00,$D7
TruckRightSpriteLevel1TwoPlayerInitial:
	dc.b $00,$C4,$0B,$04,$00,$BD,$00,$F7
	dc.b $00,$00,$00,$00,$00,$00,$00,$00
LetterSpriteLevel1TwoPlayerInitial:
	dc.b $00,$94,$00,$05,$00,$41,$01,$C0
Riley2SpriteLevel1TwoPlayerInitial:
	dc.b $01,$1D,$06,$06,$E0,$98,$00,$E2
Truck2LeftSpriteLevel1TwoPlayerInitial:
	dc.b $01,$34,$0F,$07,$20,$AD,$00,$D7
Truck2RightSpriteLevel1TwoPlayerInitial:
	dc.b $01,$34,$0B,$09,$20,$BD,$00,$F7
	dc.b $00,$00,$00,$00,$00,$00,$00,$00
Letter2SpriteLevel1TwoPlayerInitial:
	dc.b $01,$04,$00,$00,$20,$41,$01,$C0
EndSpriteLevel1TwoPlayerInitial:	
	